package com.xaicode.auth.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.lang.tree.TreeNode;
import cn.hutool.core.lang.tree.TreeUtil;
import com.xaicode.auth.annotation.AuthDataScope;
import com.xaicode.auth.base.BaseMpServiceImpl;
import com.xaicode.auth.constant.EnableEnum;
import com.xaicode.auth.entity.SysDept;
import com.xaicode.auth.mapper.SysDeptMapper;
import com.xaicode.auth.security.domain.params.SysDeptQueryParam;
import com.xaicode.auth.service.ISysDeptService;
import com.xaicode.auth.service.ISysUserService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.google.common.collect.Lists;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

@Service
public class SysDeptServiceImpl extends BaseMpServiceImpl<SysDeptMapper, SysDept> implements ISysDeptService {

    @Autowired
    SysDeptMapper sysDeptMapper;
    @Autowired
    ISysUserService sysUserService;

    @AuthDataScope(isSingleQuery = true)
    @Override
    public List<SysDept> list(SysDeptQueryParam param) {
        LambdaQueryWrapper<SysDept> lqw = Wrappers.lambdaQuery();

        List<SysDept> list = list(lqw);

        return list;
    }

    @Override
    public List<String> getParentDeptNames(Integer deptId) {
        // 获取所有部门并转换成数节点
        List<TreeNode<Integer>> nodes = list().stream()
                .map(item -> {
                    return new TreeNode<>(
                            item.getId(),
                            item.getParentId(),
                            item.getDeptName(),
                            Optional.ofNullable(item.getSortNum()).orElse(0));
                }).collect(Collectors.toList());
        // 构建树
        List<Tree<Integer>> trees = TreeUtil.build(nodes, 0);
        if (trees.isEmpty()) {
            return Lists.newArrayList();
        }
        // 获取指定节点的所有上级节点名称
        List<String> parentNames = trees.stream()
                .map(item -> {
                    // 获取指定节点
                    Tree<Integer> node = TreeUtil.getNode(item, deptId);
                    if (node != null) {
                        // 获取指定节点的所有上级节点名称
                        List<String> names = node.getParentsName(true).stream()
                                .filter(Objects::nonNull)
                                .map(String::valueOf)
                                .collect(Collectors.toList());
                        // 反转列表
                        Collections.reverse(names);
                        return names;
                    }
                    return null;
                })
                .filter(Objects::nonNull)
                .findFirst()
                .orElse(CollUtil.newArrayList());
        return parentNames;
    }

    @Override
    public List<Integer> getChildrenIds(Integer deptId) {
        // 获取所有部门并转换成数节点
        List<TreeNode<Integer>> nodes = list().stream()
                .map(item -> {
                    return new TreeNode<>(
                            item.getId(),
                            item.getParentId(),
                            item.getDeptName(),
                            0);
                }).collect(Collectors.toList());
        // 构建树
        List<Tree<Integer>> trees = TreeUtil.build(nodes, deptId);
        if (trees.isEmpty()) {
            return Lists.newArrayList();
        }

        // 获取指定节点的所有上级节点名称
        List<Integer> children = trees.stream()
                .map(Tree::getId)
                .filter(Objects::nonNull)
                .collect(Collectors.toList());
        return children;
    }

    @Override
    public void checkCanDelete(List<Integer> deptIds) {
        // 检查是否关联用户
        if (sysUserService.countByDeptIds(deptIds) == 0) {
            throw new RuntimeException("该部门已关联用户，请先取消关联");
        }

        // 检查是否关联数据权限
        if (sysDeptMapper.selectRoleDeptCountByDeptIds(deptIds) == 0) {
            throw new RuntimeException("该部门已关联角色，请先取消关联");
        }
    }

    @AuthDataScope(isSingleQuery = true)
    @Override
    public List<SysDept> listWithConcatenatedDeptName() {
        List<SysDept> depts = list(new LambdaQueryWrapper<SysDept>()
                .eq(SysDept::getStatus, EnableEnum.ENABLE.getCode())
                .orderByAsc(SysDept::getParentIds)
                .orderByAsc(SysDept::getSortNum));
        return buildDeptNameJoinStr(depts);
    }

    // ----

    /**
     * 将部门名称构造成待斜杠的集合形式，如：部门1/部门2/部门3
     *
     * @param departments .
     * @return .
     */
    private List<SysDept> buildDeptNameJoinStr(List<SysDept> departments) {
        Map<Integer, SysDept> deptMap = new HashMap<>();
        departments.forEach(dept -> deptMap.put(dept.getId(), dept));

        List<SysDept> newDeptList = new ArrayList<>();

        for (SysDept dept : departments) {
            String[] parentIds = dept.getParentIds().split(",");
            StringJoiner stringJoiner = new StringJoiner("/");
            for (String parentId : parentIds) {
                if ("0".equals(parentId)) {
                    continue;
                }
                SysDept parentDept = deptMap.get(Integer.parseInt(parentId));
                if (parentDept != null) {
                    stringJoiner.add(parentDept.getDeptName());
                }
            }
            stringJoiner.add(dept.getDeptName());

            SysDept sysDept = new SysDept();
            sysDept.setId(dept.getId());
            sysDept.setDeptName(stringJoiner.toString());
            newDeptList.add(sysDept);
        }

        return newDeptList;
    }
}
